﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Diagnostics;
using System.Drawing;
using System.Drawing.Drawing2D;
using System.Drawing.Printing;
using System.Drawing.Text;
using System.IO;
using System.Linq;
using System.Runtime.InteropServices;
using System.Text;
using System.Text.RegularExpressions;
using System.Threading.Tasks;
using System.Windows.Forms;



namespace 台签打印
{

    /// v1.1 
    /// 修正文本框空行，程序假死
    /// 
    /// v1.2 
    /// 增加几个规格尺寸
    /// 修正多个分行符，字体大小适应失败
    /// 增加字号自选，自动统一大小，最大化
    /// 制表符替换为换行(Excel复制粘贴的多列数据，自动分行)
    /// 两个字中间插入空格
    /// 
    /// v1.3
    /// 增加标签模式，一页打印多个
    /// 规格尺寸可自定义，如100x100mm，(x)号表示标签模式，(*)号表示镜像模式
    /// 规格尺寸最小30x30mm, 最大210x300mm
    /// 
    /// v1.4
    /// 修改部分文本提示信息
    /// 增加框线选择，三种模式
    /// 
    /// v1.5
    /// 高级选项，支持边距设置，主体位置偏移
    /// 支持抬头（左上）、落款（右下）两排文字设置
    /// 快捷键F7高级设置，F8打印预览
    /// 输入框显示字体大小可调，CTRL+鼠标滚轮
    /// 页面大小改为标准A4，避免打印机不兼容
    /// 
    /// v1.6
    /// 增加配置文件载入和保存
    /// 高级选项与规格尺寸对应
    /// 输入框支持TAB键输入
    /// 框线选择改为下拉选项，包含直线，虚线，点，角，无
    /// 输入框接受拖入TXT文件，Excel文件
    /// 支持拖入BMP，JPG，PNG图片作为背景
    /// 解决边框线中间粗，两边浅的问题
    /// 
    /// v1.73 
    /// 修正v1.5版引入的多个问题
    /// 添加快捷键后造成的文本框方向键，编辑键区无法使用
    /// 镜像模式，多列数据分行错误
    /// 预览和打印原点坐标偏移问题
    /// 
    /// v1.8
    /// 边框线颜色太淡，稍微加深10%
    /// 修正字体大小设为最大化时有问题，两个字的会换行
    /// 
    /// v1.9
    /// 增加边框线浓度设置0-255
    /// 打印标签可选打印标题
    /// 
    /// v2.0
    /// 单行内容分散对齐
    /// 横向支持，自动排列
    /// 代码优化


    public partial class Form1 : Form
    {
        PrintHandle ph1;  //配置
        readonly string xmlfile = "SeatPrint.xml";  //配置文件

        public Form1()
        {
            InitializeComponent();
            Application.ThreadException += (o, e) => toolStripStatusLabel1.Text = e.Exception.Message;
        }

        private void Form1_Load(object sender, EventArgs e)
        {
            Text = " SeatPrint 桌牌/台签/席卡/座位牌批量快速打印 v2.0";
            MinimumSize = Size;
            MaximumSize = Size;
            var tip = new ToolTip();
            tip.SetToolTip(comboBox1, "选择字体");
            tip.SetToolTip(comboBox2, "字体样式");
            tip.SetToolTip(comboBox3, "台签规格尺寸，可自定义\r\n(*)号表示镜像模式\r\n(x)号表示标签模式\r\n(-L)结尾表示横向");
            tip.SetToolTip(comboBox4, "字号");
            tip.SetToolTip(comboBox11, "选择打印机");
            tip.SetToolTip(button1, "打印预览");
            tip.SetToolTip(button2, "设置颜色");
            tip.SetToolTip(button3, $"设置背景图片");
            tip.SetToolTip(textBox1, "输入台签内容，一行一个\r\n插入(Tab)制表符号分行\r\n可接受拖入TXT文件，Excel文件\r\n按F7高级设置，F8打印预览");
            tip.SetToolTip(checkBox1, "分散对齐");
            tip.SetToolTip(comboBox12, "选择边框线条");
            tip.SetToolTip(trackBar1, "边框线条浓度");
            toolStripStatusLabel1.Text = "选择打印机，点击打印预览。【按F7高级设置】";

            Init(); //初始化设置
        }

        private void Init()
        {
            //载入配置文件
            ph1 = XmlData.LoadXml<PrintHandle>(xmlfile) ?? PrintHandle.Default;
            //字体
            comboBox1.Items.AddRange(FontHandle.Fonts);
            comboBox1.DataBindings.Add(new Binding("Text", ph1, nameof(ph1.FontName)));
            //字体样式
            comboBox2.Items.AddRange(Enum.GetNames(typeof(MyFontStyle)));
            comboBox2.DataBindings.Add(new Binding("Text", ph1, nameof(ph1.MyFontStyle), true));
            //字号
            comboBox4.Items.AddRange(new[] { "自动", "最大化", "48", "72", "96", "120", "144", "168", "192" });
            comboBox4.DataBindings.Add(new Binding("Text", ph1, "FontSizeText"));
            //字体颜色
            textBox1.ForeColor = Color.FromArgb(ph1.Argb);
            textBox1.DataBindings.Add(new Binding("Lines", ph1, "Lines"));
            //规格尺寸
            comboBox3.DataSource = ph1.SizeList;
            comboBox3.DataBindings.Add(new Binding("Text", ph1, "SizeText"));
            //打印机列表
            comboBox11.Items.AddRange(PrinterSettings.InstalledPrinters.Cast<string>().ToArray());
            comboBox11.DataBindings.Add(new Binding("Text", ph1, "PrinterName"));
            //线型
            comboBox12.Items.AddRange(Enum.GetNames(typeof(MyDashStyle)));
            comboBox12.DataBindings.Add(new Binding("Text", ph1, nameof(ph1.LineStyle), true));
            //分散对齐
            checkBox1.DataBindings.Add(new Binding("Checked", ph1, "InsertBlank"));
            //线框浓度
            trackBar1.DataBindings.Add(new Binding("Value", ph1, "BorderAlpha"));
            //文本框字体
            textBox1.Font = new Font(ph1.FontName, textBox1.Font.Size, (FontStyle)ph1.MyFontStyle);

            //事件
            comboBox1.SelectedIndexChanged += comboBox1_SelectedIndexChanged;
            comboBox2.SelectedIndexChanged += comboBox1_SelectedIndexChanged;
            textBox1.TextChanged += textBox1_TextChanged;
            textBox1.MouseWheel += TextBox1_MouseWheel;
            textBox1.DragDrop += TextBox1_DragDrop;
            textBox1.DragEnter += TextBox1_DragEnter;
        }

        private void TextBox1_DragEnter(object sender, DragEventArgs e)
        {
            if (e.Data.GetDataPresent(DataFormats.FileDrop)) { e.Effect = DragDropEffects.Link; }
        }

        private void TextBox1_DragDrop(object sender, DragEventArgs e)
        {
            if (e.Data.GetDataPresent(DataFormats.FileDrop))
            {
                var files = e.Data.GetData(DataFormats.FileDrop) as string[];
                var fileName = files[0];
                string extName = Path.GetExtension(fileName).ToLower();
                if (extName == ".txt")
                {
                    textBox1.Lines = File.ReadAllLines(fileName);
                }
                else if (extName == ".bmp" || extName == ".jpg" || extName == ".png")
                {
                    ph1.ImageFile = fileName;
                }
                else if (extName == ".xls" || extName == ".xlsx" || extName == ".xlsm" || extName == ".csv")
                {

                    var dlg = new Form()
                    {
                        Text = "选择表名",
                        Size = new Size(100, 80),
                        StartPosition = FormStartPosition.CenterParent,
                        FormBorderStyle = FormBorderStyle.FixedToolWindow,
                    };
                    var combo1 = new ComboBox() { Dock = DockStyle.Top, DataSource = DB.GetTables(fileName) };
                    var btn1 = new Button() { Text = "确定", Dock = DockStyle.Bottom, DialogResult = DialogResult.OK, };
                    dlg.Controls.Add(combo1);
                    dlg.Controls.Add(btn1);
                    dlg.AcceptButton = btn1;
                    if (dlg.ShowDialog() == DialogResult.OK && !string.IsNullOrEmpty(combo1.Text))
                    {
                        try
                        {
                            var dt = DB.GetDt(fileName, $"select * from [{combo1.Text}]");
                            textBox1.Lines = dt.AsEnumerable().Select(r => string.Join("\t", r.ItemArray)).ToArray();
                        }
                        catch (Exception ex)
                        {
                            toolStripStatusLabel1.Text = ex.Message;
                        }
                    }
                }
            }
        }

        private void TextBox1_MouseWheel(object sender, MouseEventArgs e)
        {
            if (ModifierKeys == Keys.Control)
            {
                if (textBox1.Font.Size <= Font.Size && e.Delta < 0) return;
                if (textBox1.Font.Size >= 48 && e.Delta > 0) return;
                textBox1.Font = new Font(textBox1.Font.FontFamily, textBox1.Font.Size + e.Delta / 120, textBox1.Font.Style);
            }
        }

        private void comboBox1_SelectedIndexChanged(object sender, EventArgs e)
        {
            var fontStyle = (FontStyle)Enum.Parse(typeof(MyFontStyle), comboBox2.Text);
            textBox1.Font = new Font(comboBox1.Text, textBox1.Font.Size, fontStyle);
        }


        private bool CreateSetup()
        {
            var result = ph1.CurrentSetup != null;
            if (!result) MessageBox.Show("规格尺寸不合要求！\r\n最小30x30mm, 最大210x300mm", "提示");
            Console.WriteLine(ph1.CurrentSetup);
            return result;
        }

        private void SetupDialog()
        {
            //配置规格尺寸
            if (!CreateSetup()) return;
            //高级设置
            new Form2(ph1.CurrentSetup).ShowDialog();
        }

        private void button1_Click(object sender, EventArgs e)
        {
            //配置规格尺寸
            if (!CreateSetup()) return;

            //数据列表
            var contentList = ph1.Lines;

            //打印标题  非镜像模式、是否为多列结构
            var printTitle = !ph1.CurrentSetup.Mirror && contentList.Where((x, i) => i < 5).All(x => x.Contains("\t"))
                && DialogResult.Yes == MessageBox.Show("是否打印第一行标题？", "提示", MessageBoxButtons.YesNo, MessageBoxIcon.Question);

            //处理后的数据
            contentList = ph1.ContentList;

            //字号处理
            var font1 = GetFontSize(ph1.CurrentSetup.Size.Millimeter2Inch(), contentList);

            //状态消息

            toolStripStatusLabel1.Text = $"数量：{contentList.Length}，" +
                $"字数：{contentList.Min(x => x.Length)}-{contentList.Max(x => x.Length)}，" + $"字体大小：{(int)font1.Size}";

            //更新配置
            ph1.Argb = textBox1.ForeColor.ToArgb();
            ph1.FontemSize = font1.Size;
            ph1.PrintTitle = printTitle;

            //保存，打印
            XmlData.SaveXml(ph1, xmlfile);
            ph1.Print();
        }

        private Font GetFontSize(Size size, string[] lines)
        {
            var font1 = textBox1.Font;
            var fontSize = comboBox4.Text;
            if (fontSize == "最大化" || fontSize == FontHandle.Max.ToString())
            {
                //最大化
                font1 = new Font(font1.FontFamily, FontHandle.Max, font1.Style);
            }
            else if (int.TryParse(fontSize, out int i) && i > 0 && i < FontHandle.Max)
            {
                //解析字号
                font1 = new Font(font1.FontFamily, i, font1.Style);
            }
            else
            {
                //自动字体大小
                using (var grfx = CreateGraphics())
                {
                    font1 = FontHandle.GetMax(grfx, size, font1, lines, ph1.CurrentSetup.MarginRatio);
                }
            }
            return font1;
        }

        private void button2_Click(object sender, EventArgs e)
        {
            var dialog = new ColorDialog();
            if (dialog.ShowDialog() == DialogResult.OK) { textBox1.ForeColor = dialog.Color; }
        }

        private void button3_Click(object sender, EventArgs e)
        {
            var dialog = new OpenFileDialog
            {
                InitialDirectory = Environment.CurrentDirectory,
                Filter = "图片文件(*.BMP;*.JPG;*.PNG)|*.BMP;*.JPG;*.PNG",
            };
            ph1.ImageFile = dialog.ShowDialog() == DialogResult.OK ? dialog.FileName : null;
        }

        private void toolStripStatusLabel2_Click(object sender, EventArgs e)
        {
            var url = "https://gitee.com/zhux3/seat-print";
            Help.ShowHelp(this, url);
        }

        private void textBox1_TextChanged(object sender, EventArgs e)
        {
            toolStripStatusLabel1.Text = textBox1.Lines.Length.ToString();
        }

        private void Form1_KeyDown(object sender, KeyEventArgs e)
        {
            if (e.KeyData == Keys.F8)
            {
                button1.PerformClick();
            }
            else if (e.KeyData == Keys.F7)
            {
                SetupDialog();
            }
        }



        #region 边框浓度
        readonly Timer timer = new Timer();
        private void comboBox12_MouseEnter(object sender, EventArgs e)
        {
            timer.Interval = 2000;
            timer.Tick += trackBar1_MouseLeave;
            timer.Start();
            trackBar1.Visible = true;
        }

        private void trackBar1_MouseLeave(object sender, EventArgs e)
        {
            trackBar1.Visible = false;
        }

        private void trackBar1_MouseEnter(object sender, EventArgs e)
        {
            timer.Stop();
            timer.Tick -= trackBar1_MouseLeave;
        }

        private void trackBar1_Scroll(object sender, EventArgs e)
        {
            ph1.BorderAlpha = trackBar1.Value;
            toolStripStatusLabel1.Text = trackBar1.Value.ToString();
        }
        #endregion
    }


}
